package com.spsoft.vatoutinv.service.vmsiscinformation.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spsoft.core.enums.ResponseEnum;
import com.spsoft.core.model.Result;
import com.spsoft.core.model.bo.TokenUser;
import com.spsoft.core.model.leqidmz.param.QueryUploadInvoiceSummaryParam;
import com.spsoft.core.model.leqidmz.param.UploadInvoiceSummaryParam;
import com.spsoft.core.model.leqidmz.response.BaseResponseVO;
import com.spsoft.core.model.leqidmz.response.QueryUploadInvoiceSummaryVO;
import com.spsoft.core.utils.BeanUtils;
import com.spsoft.core.utils.ExcelUtils;
import com.spsoft.core.utils.SecurityUtils;
import com.spsoft.einvoicetodmz.service.DmzApiClientService;
import com.spsoft.vatoutinv.constants.CommonConstant;
import com.spsoft.vatoutinv.constants.DictConstant;
import com.spsoft.vatoutinv.entity.vmsfullbswjmanager.VmsFullBswjManager;
import com.spsoft.vatoutinv.entity.vmsfulloutinvoice.VmsFullOutInvoiceDetails;
import com.spsoft.vatoutinv.entity.vmsiscinformation.VmsIscInfLog;
import com.spsoft.vatoutinv.enums.CommonEnum;
import com.spsoft.vatoutinv.mapper.VmsFullOutInvoiceDetailsMapper;
import com.spsoft.vatoutinv.mapper.VmsIscInfLogMapper;
import com.spsoft.vatoutinv.model.dto.vmsiscinformation.VmsIscInformationDto;
import com.spsoft.vatoutinv.model.dto.vmsiscinformation.VmsIscInformationUpOrCancelDto;
import com.spsoft.vatoutinv.model.vo.vmsiscinformation.VmsIscInformationComVo;
import com.spsoft.vatoutinv.model.vo.vmsiscinformation.VmsIscInformationDetailVo;
import com.spsoft.vatoutinv.model.vo.vmsiscinformation.VmsIscInformationVo;
import com.spsoft.vatoutinv.service.translate.impl.DictTranslate;
import com.spsoft.vatoutinv.service.vmsfullbswjmanager.VmsFullBswjManagerService;
import com.spsoft.vatoutinv.service.vmsfulloutinvoice.VmsFullOutInvoiceDetailsService;
import com.spsoft.vatoutinv.service.vmsiscinformation.VmsIscInformationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description: 发票汇总确认信息业务层实现类
 * @author: liwm
 * @create: 2024-01-17 16:13
 **/
@Service("vmsIscInformationService")
@RequiredArgsConstructor
@Slf4j
public class VmsIscInformationServiceImpl extends ServiceImpl<VmsIscInfLogMapper, VmsIscInfLog> implements VmsIscInformationService {

    private final VmsFullOutInvoiceDetailsService vmsFullOutInvoiceDetailsService;

    private final VmsFullOutInvoiceDetailsMapper vmsFullOutInvoiceDetailsMapper;

    private final DmzApiClientService dmzApiClientService;

    private final DictTranslate dictTranslate;

    private final VmsFullBswjManagerService vmsFullBswjManagerService;

    /**
     * 直连单位ID
     */
    @Value("${leqi.zldwId}")
    private String zldwId;

    @Override
    public Result queryIscInformationPage(VmsIscInformationDto dto) {
        /**
         * 查询企业发票汇总信息
         */
        String month = dto.getMonth();
        VmsIscInformationVo vmsIscInformationVo = new VmsIscInformationVo();
        List<VmsIscInformationComVo> vmsIscInformationComVos = vmsFullOutInvoiceDetailsMapper.selectInvoiceSummary(month, SecurityUtils.getDeptCode());
        VmsIscInformationComVo vmsIscInformationComVo = vmsIscInformationComVos.get(0);
        vmsIscInformationVo.setVmsIscInformationComVo(vmsIscInformationComVo);

        /**
         * 查询发票明细信息
         * begin
         */
        IPage<VmsIscInformationDetailVo> vmsIscInformationDetailVoIPage = this.queryIscInformationDetailPage(dto);
        vmsIscInformationVo.setVmsIscInformationDetailVo(vmsIscInformationDetailVoIPage);

        /**
         *  查询接口
         *  税局端
         *  begin
         */
        TokenUser user = SecurityUtils.getTokenUser();
        // 获取省级税务机关代码
        VmsFullBswjManager vmsFullBswjManager = vmsFullBswjManagerService.getOneByWhjg(user.getDeptCode());
        QueryUploadInvoiceSummaryParam param = new QueryUploadInvoiceSummaryParam();
        param.setXsfnsrsbh(vmsFullBswjManager.getNsrsbh());
        param.setCreateUser(user.getUserCode());
        param.setDeptCode(user.getDeptCode());
        param.setXsfsjswjgdm(vmsFullBswjManager.getQydm());
        param.setPtbh(zldwId);
        param.setYf(month);
        Result<QueryUploadInvoiceSummaryVO> result = dmzApiClientService.queryUploadInvoiceSummary(param, null);
        String code = result.getCode();
        if( !ResponseEnum.SUCCESS.getCode().equals(code) ) {
            Result<Object> objectResult = new Result<>();
            objectResult.setCode(code);
            objectResult.setMessage(result.getMessage());
            objectResult.setData(vmsIscInformationVo);
            return objectResult;
        }

        /**
         * end
         */
        //这里查询的是一个列表，实际月份不为空，查询结果只有一条当月，并加上13号限制
        QueryUploadInvoiceSummaryVO dataVo = result.getData();
        List<QueryUploadInvoiceSummaryVO.UploadInvoiceSummary> fphzqrxxList = dataVo.getFphzqrxxList();
        if( fphzqrxxList!=null && fphzqrxxList.size()>0 )  {
            QueryUploadInvoiceSummaryVO.UploadInvoiceSummary uploadInvoiceSummary = fphzqrxxList.get(0);
            VmsIscInformationComVo vo = new VmsIscInformationComVo();
            vo.setBlueInvoiceAmount(uploadInvoiceSummary.getLzfpje());
            vo.setBlueInvoiceCount( Integer.parseInt(uploadInvoiceSummary.getLzfpsl()));
            vo.setBlueInvoiceTax(uploadInvoiceSummary.getLzfpse());
            //红字发票汇总项
            vo.setRedInvoiceAmount(uploadInvoiceSummary.getHzfpje());
            vo.setRedInvoiceCount(uploadInvoiceSummary.getHzfpsl().intValue());
            vo.setRedInvoiceTax(uploadInvoiceSummary.getHzfpse());
            vmsIscInformationVo.setVmsIscInformationLqVo(vo);
        }

        return  Result.OK(vmsIscInformationVo);
    }

    @Override
    public IPage<VmsIscInformationDetailVo> queryIscInformationDetailPage(VmsIscInformationDto dto) {
        //VmsFullOutInvoiceDetails 查询当前月份的所有发票信息，并汇总
        Integer pageNo = dto.getPageNo();
        Integer pageSize = dto.getPageSize();
        Page<VmsFullOutInvoiceDetails> page = new Page<>(pageNo, pageSize);
        String month = dto.getMonth();
        LambdaQueryWrapper<VmsFullOutInvoiceDetails> lq = new LambdaQueryWrapper<>();
        extracted(lq, month);
        Page<VmsFullOutInvoiceDetails> IPage= vmsFullOutInvoiceDetailsService.page(page, lq);
        // 将发票明细转化到前端Vo
        IPage<VmsIscInformationDetailVo> vmsIscInformationVoPage = IPage.convert(v -> {
            VmsIscInformationDetailVo vo = new VmsIscInformationDetailVo();
            // 转换数据
            BeanUtils.copyBeanProp(vo, v);
            vo.setFpzt(dictTranslate.translate(DictConstant.VMS_FPZT, v.getFpzt()));
            vo.setFppz(dictTranslate.translate(DictConstant.VMS_FPLX, v.getFppz()));
            return vo;
        });
        return vmsIscInformationVoPage;
    }

    @Override
    public void exportExcel(VmsIscInformationDto dto, HttpServletResponse response) {
        // 导出  查询对应的当前月份的所有明细信息VmsFullOutInvoiceItems
        // 查询需要导出的数据
        String month = dto.getMonth();
        LambdaQueryWrapper<VmsFullOutInvoiceDetails> lq = new LambdaQueryWrapper<>();
        extracted(lq, month);

        List<VmsFullOutInvoiceDetails> vmsFullOutInvoiceDetails = vmsFullOutInvoiceDetailsMapper.selectList(lq);
        // 将发票明细转化到前端Vo，来确定导出Excel表的字段值
        List<VmsIscInformationDetailVo> vmsIscInformationVoPage = vmsFullOutInvoiceDetails.stream().map(v -> {
            VmsIscInformationDetailVo vo = new VmsIscInformationDetailVo();
            // 转换数据
            BeanUtils.copyBeanProp(vo, v);
            vo.setFpzt(dictTranslate.translate(DictConstant.VMS_FPZT, v.getFpzt()));
            vo.setFppz(dictTranslate.translate(DictConstant.VMS_FPLX, v.getFppz()));
            return vo;
            }).collect(Collectors.toList());
        // 添加序号
        for (int i = 0; i < vmsIscInformationVoPage.size(); i++) {
            vmsIscInformationVoPage.get(i).setXh(i + 1);
        }
        try {
            ExcelUtils.exportExcel(vmsIscInformationVoPage, VmsIscInformationDetailVo.class, "汇总发票明细清单", response);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 提取查询条件,查询选择月份的已上传发票数据
     * @param lq 查询条件
     * @param month 查询月份
     */
    @SuppressWarnings("unchecked")
    private static void extracted(LambdaQueryWrapper<VmsFullOutInvoiceDetails> lq, String month) {
        // 查询条件sczt=2 ；(已上传）  kprq 范围在 选择月份month ; VmsFullOutInvoiceDetails::getKprq是日期格式DATE
        lq.eq(VmsFullOutInvoiceDetails::getSczt, CommonEnum.INVOICE_UPLOAD_STATUS_2.getKey())
                .eq(VmsFullOutInvoiceDetails::getQydjid,SecurityUtils.getDeptCode())
          .apply("TO_CHAR(KPRQ, 'yyyy-mm') = {0}", month)
                // 查询条件：不查询数据源为99 导入的发票数据
           .ne(VmsFullOutInvoiceDetails::getSjly, CommonEnum.DATA_SOURCE_99.getKey())
          .orderByDesc(VmsFullOutInvoiceDetails::getKprq, VmsFullOutInvoiceDetails::getFoidid);
    }

    @Override
    public Result uploadIscInfor(VmsIscInformationUpOrCancelDto dto) {
        //调用调取乐企【发票汇总确认】接口;接口入参“业务类型”选择“0：确认
        UploadInvoiceSummaryParam param = new UploadInvoiceSummaryParam();
        TokenUser user = SecurityUtils.getTokenUser();
        VmsFullBswjManager vmsFullBswjManager = vmsFullBswjManagerService.getOneByWhjg(user.getDeptCode());
        /**
         * 必填项
         */
        param.setYwlx(CommonConstant.STR_0);
        param.setXsfnsrsbh(vmsFullBswjManager.getNsrsbh());
        param.setXsfsjswjgdm(vmsFullBswjManager.getQydm());
        // 平台编号目前使用直连单位id
        param.setPtbh(zldwId);
        param.setYf(dto.getMonth());//月份

        /**
         * 填写用户基本信息
         */
        param.setCreateUser(user.getUserCode());
        param.setDeptCode(user.getDeptCode());

        /**
         * 非必填项 -（业务类型为 “0”时必填）
         * 写一个校验方法
         */
        if (dto.getHzfpje() != null && dto.getHzfpse()!=null
                && dto.getHzfpsl()!= null && dto.getLzfpje()!= null
                && dto.getLzfpse()!= null && dto.getLzfpsl()!= null) {

            param.setHzfpje(dto.getHzfpje().setScale(2, RoundingMode.HALF_UP));//红字发票金额
            param.setHzfpse(dto.getHzfpse().setScale(2, RoundingMode.HALF_UP));
            //红字发票税额,保留两位小数

            param.setHzfpsl(dto.getHzfpsl());//红字发票数量
            param.setLzfpje(dto.getLzfpje().setScale(2, RoundingMode.HALF_UP));//蓝字发票金额
            param.setLzfpse(dto.getLzfpse().setScale(2, RoundingMode.HALF_UP));//蓝字发票税额
            param.setLzfpsl(dto.getLzfpsl());//蓝字发票数量
        }else{
            return Result.ERROR(ResponseEnum.BUSINESS_ERROR.getCode(),"红字发票金额、红字发票税额、红字发票数量、蓝字发票金额、蓝字发票税额、蓝字发票数量在上传时均不能为零和空！请确认后申请");
        }

        return getResult(param);
    }

    @NotNull
    private Result<Object> getResult(UploadInvoiceSummaryParam param) {
        Result<BaseResponseVO> baseResponseVOResult = dmzApiClientService.uploadInvoiceSummary(param, null);
        //baseResponseVOResult.getData().getReturncode();
        String code = baseResponseVOResult.getCode();
        //ResponseEnum.SUCCESS.getCode()
        if(ResponseEnum.SUCCESS.getCode().equals(code)){
            VmsIscInfLog item =new VmsIscInfLog();
            //保存结果---》数据库
            BeanUtils.copyBeanProp(item, param);
            item.setDeptcode(SecurityUtils.getDeptCode());
            Date now = new Date();
            item.setCreatedBy(SecurityUtils.getUserCode());
            item.setCreatedTime(now);
            item.setUpdatedBy(SecurityUtils.getUserCode());
            item.setUpdatedTime(now);
            item.setReturncode(code);
            item.setReturnmsg(baseResponseVOResult.getData().getReturnmsg());
            return  Result.OK(this.save(item));
        }

        return Result.ERRORT(baseResponseVOResult.getCode(),baseResponseVOResult.getMessage());
    }

    /**
     * 验证金额非空
     * @param val
     * @param msg
     * @return
     */
    @Nullable
    private Result<Object> checkIsNotNull(BigDecimal val, String msg) {
        if(val== null){
            return Result.ERROR(ResponseEnum.BUSINESS_ERROR.getCode(), msg);
        }
        return Result.OK();
    }

    @Override
    public Result cancelIscInforUpload(VmsIscInformationUpOrCancelDto dto) {
        // 调用调取乐企【发票汇总确认】接口接口入参“业务类型”选择“1：取消”

        UploadInvoiceSummaryParam param = new UploadInvoiceSummaryParam();
        TokenUser user = SecurityUtils.getTokenUser();
        VmsFullBswjManager vmsFullBswjManager = vmsFullBswjManagerService.getOneByWhjg(user.getDeptCode());
        param.setYwlx(CommonConstant.STR_1);//CommonConstant.STR_01
        /**
         * 必填项
         */
        param.setXsfnsrsbh(vmsFullBswjManager.getNsrsbh());//销售方纳税人识别号
        param.setXsfsjswjgdm(vmsFullBswjManager.getQydm());//销售方省级税务机关代码
        param.setPtbh(zldwId);//平台编号
        param.setYf(dto.getMonth());//月份
        /**
         * 填写用户基本信息
         */

        param.setCreateUser(user.getUserCode());
        param.setDeptCode(user.getDeptCode());
        /**
         * 非必填项 -（业 务 类 型 为
         *写一个校验方法
         * “0”时必填）
         * 这里不做校验
         */
        param.setHzfpje(dto.getHzfpje().setScale(2, RoundingMode.HALF_UP));//红字发票金额
        param.setHzfpse(dto.getHzfpse().setScale(2, RoundingMode.HALF_UP));//红字发票税额
        param.setHzfpsl(dto.getHzfpsl());//红字发票数量
        param.setLzfpje(dto.getLzfpje().setScale(2, RoundingMode.HALF_UP));//蓝字发票金额
        param.setLzfpse(dto.getLzfpse().setScale(2, RoundingMode.HALF_UP));//蓝字发票税额
        param.setLzfpsl(dto.getLzfpsl());//蓝字发票数量

        return getResult(param);
    }
}
